<template>
  <div class="vulnerability-review">
    <!-- 统计概览 -->
    <VulnerabilityStats :statistics="statistics" />

    <!-- 筛选条件 -->
    <VulnerabilityFilter
      :filter-form="filterForm"
      :filter-config="filterFormConfig"
      @update:filter-form="(values) => Object.assign(filterForm, values)"
      @search="handleSearch"
      @reset="handleReset"
    />

    <!-- 复核列表 -->
    <VulnerabilityReviewList
      :review-list="reviewList"
      :columns="tableColumns"
      :loading="loading"
      :pagination="pagination"
      :selected-rows="selectedRows"
      @selection-change="handleSelectionChange"
      @size-change="handleSizeChange"
      @current-page-change="handlePageChange"
      @view-detail="handleViewDetail"
      @single-review="handleSingleReview"
      @view-report="handleViewReport"
      @batch-review="handleBatchReview"
      @batch-export="handleBatchExport"
    />

    <!-- 详情弹窗 -->
    <VulnerabilityDetailDialog
      :visible="detailVisible"
      :current-vuln="currentVuln"
      :show-scan-progress="showScanProgress"
      :scan-progress="scanProgress"
      :scan-status="scanStatus"
      :estimated-completion="estimatedCompletion"
      @close="handleCloseDetail"
    />

    <!-- 复核操作弹窗 -->
    <ReviewOperationDialog
      :visible="reviewDialogVisible"
      :title="reviewDialogTitle"
      :is-batch="isBatchReview"
      :review-result="reviewResult"
      :review-opinion="reviewOpinion"
      :auto-scan="autoScan"
      :generate-report="generateReport"
      :show-scan-progress="showScanProgressInDialog"
      :scan-progress="scanProgress"
      :scan-status="scanStatus"
      :estimated-completion="estimatedCompletion"
      :is-scanning="isScanning || isGeneratingReport"
      :is-generating-report="isGeneratingReport"
      @update:visible="reviewDialogVisible = $event"
      @update:review-result="reviewResult = $event"
      @update:review-opinion="reviewOpinion = $event"
      @update:auto-scan="autoScan = $event"
      @update:generate-report="generateReport = $event"
      @submit="submitReview"
      @close="handleCloseReviewDialog"
      @save-draft="saveDraft"
    />
  </div>
</template>

<script setup lang="ts">
import { ref, reactive, onMounted, onUnmounted } from "vue";
import { ElMessage, ElMessageBox } from "element-plus";
import type { FormItemConfig } from "@/components/DynamicForm/types";
import type {
  TableColumn,
  PaginationConfig,
} from "@/components/DynamicTable/types";
import {
  getReviewList,
  getReviewDetail,
  submitReview as submitReviewApi,
  batchReview,
  getScanProgress,
  getScanReport,
  getReviewStatistics,
} from "../../servers";
import { severityLabels } from "../../helps";

// 引入拆分的子组件
import VulnerabilityStats from "./components/VulnerabilityStats.vue";
import VulnerabilityFilter from "./components/VulnerabilityFilter.vue";
import VulnerabilityReviewList from "./components/VulnerabilityReviewList.vue";
import VulnerabilityDetailDialog from "./components/VulnerabilityDetailDialog.vue";
import ReviewOperationDialog from "./components/ReviewOperationDialog.vue";

// 状态管理
const loading = ref(false);
const detailVisible = ref(false);
const selectedRows = ref<any[]>([]);

// 筛选表单数据
const filterForm = reactive({
  review_status: "all",
  asset: "all",
  severity: "all",
  keyword: "",
});

// 筛选表单配置
const filterFormConfig: FormItemConfig[] = [
  {
    key: "review_status",
    name: "复核状态",
    type: "select",
    params: { clearable: false },
    options: [
      { label: "全部", value: "all" },
      { label: "待复核", value: "pending" },
      { label: "已确认", value: "confirmed" },
      { label: "误报", value: "false_positive" },
    ],
    col: { span: 5 },
  },
  {
    key: "asset",
    name: "资产",
    type: "select",
    params: { clearable: false },
    options: [
      { label: "全部", value: "all" },
      { label: "资产A", value: "assetA" },
      { label: "资产B", value: "assetB" },
      { label: "资产C", value: "assetC" },
      { label: "资产D", value: "assetD" },
    ],
    col: { span: 5 },
  },
  {
    key: "severity",
    name: "严重程度",
    type: "select",
    params: { clearable: false },
    options: [
      { label: "全部", value: "all" },
      { label: "严重", value: "critical" },
      { label: "高危", value: "high" },
      { label: "中危", value: "medium" },
      { label: "低危", value: "low" },
    ],
    col: { span: 5 },
  },
  {
    key: "keyword",
    name: "关键词",
    type: "input",
    params: { placeholder: "输入关键词搜索" },
    col: { span: 6 },
  },
];

// 表格列配置
const tableColumns: TableColumn[] = [
  { label: "漏洞编号", prop: "cveId", minWidth: 120 },
  { label: "资产", prop: "asset", minWidth: 100 },
  { label: "严重程度", prop: "severity", minWidth: 100, slot: "severity" },
  { label: "状态", prop: "status", minWidth: 100, slot: "status" },
  { label: "漏洞名称", prop: "name", minWidth: 200, showOverflowTooltip: true },
  {
    label: "匹配度",
    prop: "matchScore",
    minWidth: 150,
    formatter: (row: any) => `★★★★★ ${row.matchScore}%`,
  },
  { label: "匹配时间", prop: "matchTime", minWidth: 160 },
  { label: "操作", prop: "action", minWidth: 140, slot: "action" },
];

// 复核列表数据
const reviewList = ref<any[]>([]);

// 统计数据
const statistics = reactive({
  pending: 0,
  in_review: 0,
  approved: 0,
  rejected: 0,
  total: 0,
});

// 分页配置
const pagination = reactive<PaginationConfig>({
  currentPage: 1,
  pageSize: 10,
  total: 0,
  pageSizes: [10, 20, 50, 100],
  layout: "prev, pager, next, jumper, total",
  background: true,
});

// 详情弹窗数据
const currentVuln = ref<any>(null);

// 复核操作弹窗数据
const reviewDialogVisible = ref(false);
const reviewDialogTitle = ref("复核操作");
const isBatchReview = ref(false);
const currentMatchId = ref<string>("");
const currentMatchIds = ref<string[]>([]);
const reviewResult = ref("pending");
const reviewOpinion = ref("");
const autoScan = ref(true);
const generateReport = ref(true);
const showScanProgressInDialog = ref(false);
const isScanning = ref(false);

// 扫描进度相关
const showScanProgress = ref(false);
const scanProgress = ref(0);
const scanStatus = ref("等待扫描...");
const estimatedCompletion = ref("");
const currentScanId = ref<string>("");
const isGeneratingReport = ref(false);
const reportGenerated = ref(false);
let scanProgressTimer: ReturnType<typeof setInterval> | null = null;

// 搜索
const handleSearch = (values: any) => {
  pagination.currentPage = 1;
  fetchReviewList(values);
  fetchReviewStatistics();
};

// 重置
const handleReset = () => {
  Object.assign(filterForm, {
    review_status: "all",
    asset: "all",
    severity: "all",
    keyword: "",
  });
  pagination.currentPage = 1;
  fetchReviewList();
  fetchReviewStatistics();
};

// 获取复核列表数据
const fetchReviewList = async (values: any = {}) => {
  loading.value = true;
  try {
    const params = {
      page: pagination.currentPage,
      per_page: pagination.pageSize,
      ...values,
    };
    const { data } = await getReviewList(params);
    if (data) {
      reviewList.value = (data.items || []).map((item: any) => ({
        id: item.match_id,
        match_id: item.match_id,
        intelligence_id: item.intelligence_id,
        cveId: item.cve_id,
        name: item.title,
        severity: mapSeverity(item.severity),
        status: mapReviewStatus(item.review_status || item.verification_status),
        statusText: getStatusText(
          item.review_status || item.verification_status
        ),
        asset: item.asset?.hostname || item.asset?.ip || "未知资产",
        asset_id: item.asset?.asset_id,
        matchScore: Math.round((item.match_info?.confidence_score || 0) * 100),
        matchTime: item.match_info?.created_at || item.created_at,
        cvss_score: item.cvss_score,
        scanId: item.scan_status?.scan_id || null,
        raw: item,
      }));
      pagination.total = data.total || 0;
    }
  } catch (error: any) {
    ElMessage.error(error?.message || "获取复核列表失败");
  } finally {
    loading.value = false;
  }
};

// 映射严重程度
const mapSeverity = (severity: string) => {
  const map: Record<string, string> = {
    critical: "严重",
    high: "高危",
    medium: "中危",
    low: "低危",
  };
  return map[severity] || severity;
};

// 映射复核状态
const mapReviewStatus = (status: string) => {
  const map: Record<string, string> = {
    pending: "pending",
    confirmed: "confirmed",
    false_positive: "false_positive",
    in_review: "pending",
    approved: "confirmed",
    rejected: "false_positive",
  };
  return map[status] || status;
};

// 获取状态文本
const getStatusText = (status: string) => {
  const map: Record<string, string> = {
    pending: "待复核",
    confirmed: "已确认",
    false_positive: "误报",
    in_review: "待复核",
    approved: "已确认",
    rejected: "误报",
  };
  return map[status] || status;
};

// 分页处理
const handleSizeChange = (size: number) => {
  pagination.pageSize = size;
  pagination.currentPage = 1;
  fetchReviewList();
};

const handlePageChange = (page: number) => {
  pagination.currentPage = page;
  fetchReviewList();
};

// 选择变化
const handleSelectionChange = (rows: any[]) => {
  selectedRows.value = rows;
};

// 查看详情
const handleViewDetail = async (row: any) => {
  loading.value = true;
  try {
    const matchId = row.match_id || row.id;
    const { data } = await getReviewDetail(matchId);
    if (data) {
      const intelligence = data.intelligence_info || {};
      const assetInfo = data.scan_asset_info || {};
      const matchInfo = data.match_info || {};
      const matchDetails = data.match_details || {};

      currentMatchId.value = matchInfo.match_id;
      currentVuln.value = {
        match_id: matchInfo.match_id,
        intelligence_id: intelligence.id || intelligence.intelligence_id,
        cveId: intelligence.cve_id,
        name: intelligence.name,
        description: intelligence.description || "暂无描述信息",
        severity: mapSeverity(intelligence.severity || ""),
        cvss: intelligence.cvss_score || 0,
        matchScore: Math.round((matchInfo.confidence_score || 0) * 100),
        verificationStatus: matchInfo.verification_status || "pending",
        isSuspect: matchDetails.is_suspect || false,
        assetInfo: {
          ip: assetInfo.ip,
          port: assetInfo.port,
          service: assetInfo.service,
          banner: assetInfo.banner,
          products: assetInfo.products || [],
          tags: assetInfo.tags || [],
        },
        matchKeywords: matchDetails.keywords || {},
        affectedProducts: intelligence.affected_products || [],
        recommendedPocs: data.recommended_pocs || [],
        reviewHistory: data.review_history || [],
        timeline: data.timeline || [],
        scanHistory: data.scan_history || [],
      };

      reviewResult.value =
        matchInfo.verification_status === "confirmed"
          ? "approved"
          : matchInfo.verification_status === "false_positive"
          ? "rejected"
          : "pending";

      // 检查扫描状态
      if (data.scan_history?.length) {
        const latestScan = data.scan_history[data.scan_history.length - 1];
        if (
          latestScan.scan_id &&
          ["running", "pending"].includes(latestScan.status)
        ) {
          currentScanId.value = latestScan.scan_id;
          showScanProgress.value = true;
          startScanProgressPolling(latestScan.scan_id);
        }
      } else {
        showScanProgress.value = false;
        currentScanId.value = "";
      }
    }
  } catch (error: any) {
    ElMessage.error(error?.message || "获取复核详情失败");
  } finally {
    loading.value = false;
  }
  detailVisible.value = true;
};

// 单个审核
const handleSingleReview = (row: any) => {
  isBatchReview.value = false;
  currentMatchId.value = row.match_id || row.id;
  currentMatchIds.value = [];
  reviewResult.value = "pending";
  reviewDialogTitle.value = `审核漏洞 ${row.cveId || row.name}`;
  reviewOpinion.value = "";
  autoScan.value = true;
  generateReport.value = true;
  showScanProgressInDialog.value = false;
  isScanning.value = false;
  stopScanProgressPolling();
  reviewDialogVisible.value = true;
};

// 查看报告
const handleViewReport = async (row: any) => {
  const scanId = row.scanId || row.raw?.scan_info?.scan_id;
  if (!scanId) {
    ElMessage.warning("该漏洞尚未生成扫描报告");
    return;
  }

  loading.value = true;
  try {
    const { data } = await getScanReport(scanId);
    if (data) {
      ElMessageBox.alert(
        `
        <div style="text-align: left;">
          <p><strong>扫描ID:</strong> ${data.scan_id}</p>
          <p><strong>CVE ID:</strong> ${data.cve_id}</p>
          <p><strong>目标:</strong> ${data.target}</p>
          <p><strong>扫描结果:</strong> ${getScanResultText(
            data.scan_result
          )}</p>
          ${
            data.report_url
              ? `<p><strong>报告链接:</strong> <a href="${data.report_url}" target="_blank">查看详细报告</a></p>`
              : ""
          }
        </div>
      `,
        "扫描报告",
        { dangerouslyUseHTMLString: true, type: "info" }
      );
    }
  } catch (error: any) {
    ElMessage.error(error?.message || "获取扫描报告失败");
  } finally {
    loading.value = false;
  }
};

// 批量审核
const handleBatchReview = () => {
  if (selectedRows.value.length === 0) {
    ElMessage.warning("请选择需要操作的漏洞");
    return;
  }

  isBatchReview.value = true;
  currentMatchIds.value = selectedRows.value.map(
    (row) => row.match_id || row.id
  );
  currentMatchId.value = "";
  reviewResult.value = "pending";
  reviewDialogTitle.value = `批量审核 ${selectedRows.value.length} 个漏洞`;
  reviewOpinion.value = "";
  autoScan.value = true;
  generateReport.value = true;
  showScanProgressInDialog.value = false;
  isScanning.value = false;
  reviewDialogVisible.value = true;
};

// 批量导出
const handleBatchExport = () => {
  if (selectedRows.value.length === 0) {
    ElMessage.warning("请选择需要导出的漏洞");
    return;
  }
  ElMessage.info(`导出 ${selectedRows.value.length} 个漏洞数据`);
};

// 提交复核
const submitReview = async () => {
  const matchId = currentMatchId.value;
  if (!matchId) {
    ElMessage.warning("缺少匹配ID");
    return;
  }

  if (
    (reviewResult.value === "approved" || reviewResult.value === "rejected") &&
    !reviewOpinion.value.trim()
  ) {
    ElMessage.warning("通过或驳回必须输入复核意见");
    return;
  }

  try {
    loading.value = true;
    const decisionMap: Record<string, string> = {
      approved: "confirmed",
      rejected: "false_positive",
      pending: "pending",
    };
    const decision = decisionMap[reviewResult.value] || reviewResult.value;

    // 提交复核（单个）
    const result = await submitReviewApi({
      match_ids: [matchId],
      decision,
      comment: reviewOpinion.value,
      auto_scan: autoScan.value,
      scan_options: generateReport.value
        ? { poc_types: ["nuclei", "custom"], timeout: 300 }
        : undefined,
    });

    ElMessage.success(result?.message || "复核提交成功");

    console.log(autoScan.value, "autoScan.value");
    console.log(result, "result");
    console.log(generateReport.value, "generateReport.value");

    // return;
    // 如果勾选了自动扫描，需要等待扫描完成
    if (autoScan.value) {
      // 检查 scan_task 和 scan_task_id 是否存在
      const resultData = result as any;
      const scanTask = resultData?.scan_task;
      const scanTaskId = scanTask?.scan_task_id || resultData?.scan_task_id;

      if (scanTask && scanTaskId) {
        // 立即设置扫描状态，防止弹窗关闭
        isScanning.value = true;
        showScanProgressInDialog.value = true;
        currentScanId.value = scanTaskId;
        scanProgress.value = 0;
        scanStatus.value = "扫描已启动";
        estimatedCompletion.value = "计算中...";
        // 开始轮询扫描进度
        startScanProgressPollingForDialog(scanTaskId);
        // 不关闭弹窗，等待扫描完成
        return;
      } else {
        // 没有找到 scan_task 或 scan_task_id，抛出错误并关闭弹窗
        const matchIdStr = isBatchReview.value
          ? currentMatchIds.value.join(", ")
          : currentMatchId.value;
        ElMessage.error(`未找到POC，无法为${matchIdStr}创建扫描任务`);
        closeReviewDialogAndRefresh();
      }
    } else {
      // 没有勾选自动扫描，直接关闭弹窗
      closeReviewDialogAndRefresh();
    }
  } catch (error: any) {
    ElMessage.error(error?.message || "提交复核失败");
  } finally {
    loading.value = false;
  }
};

// 保存草稿
const saveDraft = () => {
  const draft = {
    match_id: currentMatchId.value,
    reviewResult: reviewResult.value,
    reviewOpinion: reviewOpinion.value,
    autoScan: autoScan.value,
    generateReport: generateReport.value,
  };
  localStorage.setItem(
    `review_draft_${currentMatchId.value}`,
    JSON.stringify(draft)
  );
  ElMessage.success("草稿已保存");
};

// 关闭详情弹窗
const handleCloseDetail = () => {
  detailVisible.value = false;
  currentVuln.value = null;
  showScanProgress.value = false;
  stopScanProgressPolling();
};

// 关闭复核操作弹窗
const handleCloseReviewDialog = () => {
  if (isScanning.value) {
    ElMessage.warning("扫描进行中，请等待扫描完成");
    return;
  }
  if (isGeneratingReport.value) {
    ElMessage.warning("报告生成中，请等待报告生成完成");
    return;
  }
  if (showScanProgressInDialog.value && scanProgress.value < 100) {
    ElMessage.warning("扫描未完成，请等待扫描完成");
    return;
  }
  reviewDialogVisible.value = false;
  isBatchReview.value = false;
  currentMatchId.value = "";
  currentMatchIds.value = [];
  reviewResult.value = "pending";
  reviewOpinion.value = "";
  autoScan.value = true;
  generateReport.value = true;
  showScanProgressInDialog.value = false;
  isScanning.value = false;
  isGeneratingReport.value = false;
  reportGenerated.value = false;
  stopScanProgressPolling();
};

// 获取扫描结果文本
const getScanResultText = (result: string) => {
  const map: Record<string, string> = {
    vulnerable: "存在漏洞",
    safe: "安全",
    unknown: "未知",
  };
  return map[result] || result;
};

// 扫描进度轮询相关
const fetchScanProgress = async (scanId: string) => {
  try {
    const { data } = await getScanProgress(scanId);
    if (data) {
      scanProgress.value = data.progress || 0;
      scanStatus.value =
        data.status === "running"
          ? `扫描中... (${data.tested_pocs || 0}/${
              data.total_pocs || 0
            } POC已测试)`
          : data.status === "completed"
          ? "扫描完成"
          : data.status === "failed"
          ? "扫描失败"
          : "等待扫描...";

      if (data.estimated_completion)
        estimatedCompletion.value = data.estimated_completion;
      if (["completed", "failed"].includes(data.status))
        stopScanProgressPolling();
    }
  } catch (error) {
    console.error("获取扫描进度失败:", error);
  }
};

const startScanProgressPollingForDialog = (scanTaskId: string) => {
  stopScanProgressPolling();
  fetchScanProgressForDialog(scanTaskId);
  scanProgressTimer = setInterval(
    () => fetchScanProgressForDialog(scanTaskId),
    3000
  );
};

const fetchScanProgressForDialog = async (scanTaskId: string) => {
  try {
    const { data } = await getScanProgress(scanTaskId);
    if (data) {
      scanProgress.value = data.progress || 0;
      if (data.estimated_completion) {
        estimatedCompletion.value = data.estimated_completion;
      }

      if (data.status === "running") {
        scanStatus.value = `扫描中... (${data.tested_pocs || 0}/${
          data.total_pocs || 0
        } POC已测试)`;
        if (data.current_poc)
          scanStatus.value += ` - 当前: ${data.current_poc}`;
      } else if (data.status === "completed") {
        scanStatus.value = "扫描完成";
        isScanning.value = false;
        stopScanProgressPolling();

        // 如果勾选了生成报告，需要等待报告生成完成
        if (generateReport.value) {
          isGeneratingReport.value = true;
          scanStatus.value = "正在生成报告...";
          await checkReportGeneration(scanTaskId);
        } else {
          // 没有勾选生成报告，直接关闭
          setTimeout(() => {
            closeReviewDialogAndRefresh();
          }, 1000);
        }
      } else if (data.status === "failed") {
        scanStatus.value = "扫描失败";
        isScanning.value = false;
        isGeneratingReport.value = false;
        stopScanProgressPolling();
        ElMessage.warning("扫描失败，但复核已提交");
        setTimeout(() => {
          closeReviewDialogAndRefresh();
        }, 2000);
      }
    }
  } catch (error) {
    console.error("获取扫描进度失败:", error);
  }
};

// 检查报告生成状态
const checkReportGeneration = async (scanTaskId: string) => {
  const maxRetries = 30; // 最多重试30次（约90秒）
  let retries = 0;

  const checkReport = async () => {
    try {
      const { data } = await getScanReport(scanTaskId);
      if (data && data.report_url) {
        // 报告已生成
        reportGenerated.value = true;
        isGeneratingReport.value = false;
        scanStatus.value = "扫描完成，报告已生成";
        ElMessage.success("扫描完成，报告已生成");
        setTimeout(() => {
          closeReviewDialogAndRefresh();
        }, 1500);
      } else {
        // 报告还未生成，继续等待
        retries++;
        if (retries < maxRetries) {
          setTimeout(checkReport, 3000); // 每3秒检查一次
        } else {
          // 超时，提示用户
          isGeneratingReport.value = false;
          scanStatus.value = "报告生成超时";
          ElMessage.warning("报告生成超时，但扫描已完成");
          setTimeout(() => {
            closeReviewDialogAndRefresh();
          }, 2000);
        }
      }
    } catch (error: any) {
      // 如果报告接口返回404或其他错误，可能是报告还未生成
      retries++;
      if (retries < maxRetries) {
        setTimeout(checkReport, 3000);
      } else {
        // 超时，提示用户
        isGeneratingReport.value = false;
        scanStatus.value = "报告生成超时";
        ElMessage.warning("报告生成超时，但扫描已完成");
        setTimeout(() => {
          closeReviewDialogAndRefresh();
        }, 2000);
      }
    }
  };

  // 开始检查报告
  checkReport();
};

const startScanProgressPolling = (scanId: string) => {
  stopScanProgressPolling();
  fetchScanProgress(scanId);
  scanProgressTimer = setInterval(() => fetchScanProgress(scanId), 3000);
};

const stopScanProgressPolling = () => {
  if (scanProgressTimer) {
    clearInterval(scanProgressTimer);
    scanProgressTimer = null;
  }
};

const closeReviewDialogAndRefresh = () => {
  reviewDialogVisible.value = false;
  Promise.all([fetchReviewList(), fetchReviewStatistics()]);
  handleCloseReviewDialog();
};

// 获取复核统计
const fetchReviewStatistics = async () => {
  try {
    const { data } = await getReviewStatistics();
    if (data?.overview) {
      statistics.pending = data.overview.pending || 0;
      statistics.in_review = data.overview.in_remediation || 0;
      statistics.approved = data.overview.confirmed || 0;
      statistics.rejected = data.overview.false_positive || 0;
      statistics.total = data.overview.total_matches || 0;
    }
  } catch (error) {
    console.error("获取复核统计失败:", error);
  }
};

// 组件生命周期
onMounted(() => {
  fetchReviewList();
  fetchReviewStatistics();
});

onUnmounted(() => {
  stopScanProgressPolling();
});

// 暴露方法
defineExpose({ refreshData: fetchReviewList });
</script>

<style scoped lang="scss">
.vulnerability-review {
  padding: 20px;
  background-color: #f5f7fa;
  min-height: 100vh;
}
</style>
